package danran.dbapi.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import danran.dbapi.domain.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Classname DruidPoolManager
 * @Description TODO
 * @Date 2022/1/17 11:09
 * @Created by RanCoder
 */
public class DruidPoolManager {
    private static final Logger log = LoggerFactory.getLogger(DruidPoolManager.class);
    private static Lock lock = new ReentrantLock();
    private static Lock delLock = new ReentrantLock();
    // 数据源id —— DruidDataSource
    static Map<String, DruidDataSource> map = new HashMap<>();

    public static DruidDataSource getConnectionPool(DataSource ds) {
        if (map.containsKey(ds.getId())) {
            return map.get(ds.getId());
        } else {
            // need to create a new connection pool and add it into the map.
            lock.lock();
            try {
                log.info(Thread.currentThread().getName() + "Get the add lock");
                if (!map.containsKey(ds.getId())) {// to avoid other thread already added and then add again
                    DruidDataSource druidDataSource = new DruidDataSource();
                    druidDataSource.setName(ds.getName());
                    druidDataSource.setUrl(ds.getUrl());
                    druidDataSource.setUsername(ds.getUsername());
                    druidDataSource.setPassword(ds.getPassword());
                    druidDataSource.setDriverClassName(ds.getDriver());
                    druidDataSource.setConnectionErrorRetryAttempts(3);
                    druidDataSource.setBreakAfterAcquireFailure(true);

                    map.put(ds.getId(), druidDataSource);
                    log.info("创建Druid连接池成功: {}", ds.getName());
                }
                return map.get(ds.getId());
            } catch (Exception e) {
                return null;
            } finally {
                lock.unlock();
            }
        }
    }


    public static void removeConnectionPool(String id) {
        delLock.lock();
        log.info("{} get the del lock", Thread.currentThread().getName());
        try {
            DruidDataSource druidDataSource = map.get(id);
            if (druidDataSource != null) {
                druidDataSource.close();
                map.remove(id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            delLock.unlock();
        }
    }

    public static DruidPooledConnection getPooledConnection(DataSource ds) throws SQLException {
        DruidDataSource connectionPool = DruidPoolManager.getConnectionPool(ds);
        if (connectionPool != null) {
            log.info("获取连接成功");
            return connectionPool.getConnection();
        }
        log.info("连接失败");
        return null;
    }
}
